"""
系统管理相关接口
用户 / 角色 / 权限 / 审计日志
"""
from datetime import datetime
from typing import List

from fastapi import APIRouter, Depends, Request, Query, Path, Body

from app.common.auth import check_permission, audit_log
from app.common.common import AuditLogDep, DbDep, PaginationDep
from app.crud import user_crud, role_crud, permission_crud, audit_log_crud
from app.crud.address_crud import (
	get_base_address_list, get_base_address_by_id,
	create_base_address, update_base_address, delete_base_address
)
from app.crud.device_crud import update_station_manager, update_box_manager, update_rtu_manager
from app.schemas.address_schemas import (
	AddressCreate, AddressUpdate, AddressResponse,
	AddressListRequest, AddressListResponse
)
from app.schemas.system_schemas import (
	UserListRequest, UserListResponse, UserRoleAssignRequest,
	RoleCreate, RoleUpdate, RoleResponse, RoleListRequest, RoleListResponse,
	RolePermissionAssignRequest, PermissionCreate, PermissionUpdate,
	PermissionResponse, PermissionTreeResponse, PermissionListRequest, PermissionListResponse, AuditLogRequest,
	AuditLogListResponse, OperationStatisticsResponse, ManagerUpdateRequest
)
from app.schemas.user_schemas import UserInDB
from common.exceptions import BizException, ErrorCode
from common.response import ApiResponse

router = APIRouter(prefix="/system", tags=["系统管理"])

require_user_manage = check_permission("system:user:manage")
require_role_manage = check_permission("system:role:manage")
require_perm_manage = check_permission("system:permission:manage")
require_audit_view = check_permission("system:audit:view")
require_device_manage = check_permission("system:device:manage")
require_address_manage = check_permission("system:address:manage")
require_address_view = check_permission("system:address:view")
require_system_admin = check_permission("system:admin")


# ============ 系统监控 ============
@router.get("/health/database", response_model=ApiResponse[dict], summary="数据库连接池状态")
async def get_database_health(
		_: UserInDB = Depends(require_system_admin),
) -> ApiResponse[dict]:
	"""获取数据库连接池状态"""
	try:
		from common.database import _MySQLPool
		stats = _MySQLPool.get_pool_stats()
		return ApiResponse.success(stats, "数据库连接池状态获取成功")
	except Exception as e:
		return ApiResponse.error(f"获取数据库连接池状态失败: {str(e)}", code=500)


# ============ 用户管理 ============
@router.post("/users/list", response_model=ApiResponse[UserListResponse], summary="获取用户列表")
async def get_users(
		request: UserListRequest,
		db: DbDep,
		_: UserInDB = Depends(require_user_manage),
) -> ApiResponse[UserListResponse]:
	total, users = await user_crud.get_user_list(db, request)
	return ApiResponse.success(UserListResponse(total=total, items=users))


@router.post(
	"/users/{user_code}/roles",
	response_model=ApiResponse[dict],
	summary="为用户分配角色",
)
async def assign_user_roles(
		user_code: str,
		request: UserRoleAssignRequest,
		db: DbDep,
		_: UserInDB = Depends(require_user_manage),
		# 审计日志：target_id 使用被操作用户的 user_code
		_audit: None = Depends(audit_log()),
) -> ApiResponse[dict]:
	"""
	为用户分配角色
	1. 依赖注入记录审计日志，target_id 自动填充为被操作用户
	2. 参数不一致直接抛 400
	3. 不再手动调用 AuditLogger.log_user_role_assign
	"""
	if request.user_code != user_code:
		raise BizException.from_error_code(
			ErrorCode.BAD_REQUEST, message="参数不一致"
		)

	await user_crud.assign_roles_to_user(db, user_code, request.role_ids)
	return ApiResponse.success(message="角色分配成功")


@router.delete("/users/{user_code}/roles", response_model=ApiResponse[dict],
			   summary="取消用户角色（空列表=取消全部）")
async def remove_user_roles(
		db: DbDep,
		user_code: str,
		role_ids: List[int] = Query([], description="要取消的角色ID，空=全部"),
		_: UserInDB = Depends(require_user_manage),
) -> ApiResponse[dict]:
	"""取消用户角色（不记录审计）"""
	await user_crud.remove_roles_from_user(db, user_code, role_ids)
	msg = f"已取消角色 {role_ids}" if role_ids else "已取消全部角色"
	return ApiResponse.success(message=msg)


@router.put("/users/{user_id}/disable", response_model=ApiResponse[dict], summary="禁用用户")
async def disable_user(
		user_id: int,
		db: DbDep,
		current_user: UserInDB = Depends(require_user_manage),
		http_request: Request = None,
) -> ApiResponse[dict]:
	ok = await user_crud.disable_user(db, user_id)
	if not ok:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="用户不存在")
	await audit_log_crud.create_audit_log(
		db=db, user_code=current_user.user_code, action="DISABLE_USER",
		target_type="USER", target_id=str(user_id),
		request_ip=http_request.client.host if http_request else "unknown",
		request_uri=str(http_request.url) if http_request else f"/system/users/{user_id}/disable",
	)
	return ApiResponse.success(message="用户已禁用")


@router.put("/users/{user_id}/enable", response_model=ApiResponse[dict], summary="启用用户")
async def enable_user(
		user_id: int,
		db: DbDep,
		current_user: UserInDB = Depends(require_user_manage),
		_audit: None = Depends(audit_log()),
		http_request: Request = None,
) -> ApiResponse[dict]:
	ok = await user_crud.enable_user(db, user_id)
	if not ok:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="用户不存在")
	await audit_log_crud.create_audit_log(
		db=db, user_code=current_user.user_code, action="ENABLE_USER",
		target_type="USER", target_id=str(user_id),
		request_ip=http_request.client.host if http_request else "unknown",
		request_uri=str(http_request.url) if http_request else f"/system/users/{user_id}/enable",
	)
	return ApiResponse.success(message="用户已启用")


# ============ 角色管理 ============
@router.post("/roles/list", response_model=ApiResponse[RoleListResponse], summary="获取角色列表（含权限）")
async def get_roles(
		request: RoleListRequest,
		db: DbDep,
		_: UserInDB = Depends(require_user_manage),
) -> ApiResponse[RoleListResponse]:
	total, roles = await role_crud.get_role_list(db, request)
	return ApiResponse.success(RoleListResponse(total=total, items=roles))


@router.post("/roles", response_model=ApiResponse[RoleResponse], summary="创建角色",
			 )
async def create_role(
		request: RoleCreate,
		db: DbDep,
		_: UserInDB = Depends(require_role_manage),
		_audit: None = Depends(audit_log()),
) -> ApiResponse[RoleResponse]:
	"""
	创建角色
	1. 依赖注入 _audit 会在进入函数前写入审计日志，result 初始为 1（成功）
	2. 若发生业务异常，全局异常处理器自动将 result 置为 0
	3. 函数体内无需再手动写审计日志
	"""
	# 写入数据库
	role_id = await role_crud.create_role(db, request)
	# 将业务主键挂到 request.state，供依赖注入解析 target_id 占位符

	# 查询完整信息并返回
	role = await role_crud.get_role_by_id(db, role_id)
	return ApiResponse.success(RoleResponse.model_validate(role))


@router.put("/roles/{role_id}", response_model=ApiResponse[RoleResponse], summary="更新角色")
async def update_role(
		role_id: int,
		request: RoleUpdate,
		db: DbDep,
		_: UserInDB = Depends(require_role_manage),
		_audit: None = Depends(audit_log()),
) -> ApiResponse[RoleResponse]:
	ok = await role_crud.update_role(db, role_id, request)
	if not ok:
		# 抛出业务异常后，异常处理器会把 audit_log.result 置为 0
		raise BizException.from_error_code(
			ErrorCode.NOT_FOUND, message="角色不存在"
		)

	# 查询最新数据并返回
	role = await role_crud.get_role_by_id(db, role_id)
	return ApiResponse.success(RoleResponse.model_validate(role))


@router.delete("/roles/{role_id}", response_model=ApiResponse[dict], summary="删除角色", )
async def delete_role(
		role_id: int,
		db: DbDep,
		_: UserInDB = Depends(require_role_manage),
		# 审计日志：依赖注入，异常时自动置 result=0
		_audit: None = Depends(audit_log()),
) -> ApiResponse[dict]:
	"""
	删除角色
	1. 依赖注入负责写审计日志（含请求 IP、路径、动作动词）
	2. 业务异常时全局异常处理器自动将 result 更新为 0
	3. 函数体内无需再手动调用 AuditLogger
	"""
	ok = await role_crud.delete_role(db, role_id)
	if not ok:
		raise BizException.from_error_code(
			ErrorCode.NOT_FOUND, message="角色不存在"
		)
	return ApiResponse.success(message="角色删除成功")


@router.post(
	"/roles/{role_id}/permissions",
	response_model=ApiResponse[dict],
	summary="为角色分配权限",
)
async def assign_role_permissions(
		role_id: int,
		request: RolePermissionAssignRequest,
		db: DbDep,
		_: UserInDB = Depends(require_role_manage),
		_audit: None = Depends(audit_log()),
) -> ApiResponse[dict]:
	"""
	为角色批量分配权限
	1. 依赖注入记录审计日志，request_body 已自动脱敏
	2. 参数不一致直接抛 400，异常处理器自动更新 audit result=0
	3. 不再手动调用 AuditLogger.log_permission_assign
	"""
	if request.role_id != role_id:
		raise BizException.from_error_code(
			ErrorCode.BAD_REQUEST, message="参数不一致"
		)

	await role_crud.assign_permissions_to_role(db, role_id, request.permission_ids)
	return ApiResponse.success(message="权限分配成功")


@router.delete("/roles/{role_id}/permissions", response_model=ApiResponse[dict],
			   summary="取消角色权限（空列表=取消全部）")
async def remove_role_permissions(
		db: DbDep,
		role_id: int,
		permission_ids: List[int] = Query([], description="权限ID，空=全部"),
		_: UserInDB = Depends(require_role_manage),
) -> ApiResponse[dict]:
	"""取消角色权限（不记录审计）"""
	await role_crud.remove_permissions_from_role(db, role_id, permission_ids)
	msg = f"已取消权限 {permission_ids}" if permission_ids else "已取消全部权限"
	return ApiResponse.success(message=msg)


# ============ 权限管理 ============
@router.post("/permissions/list", response_model=ApiResponse[PermissionListResponse], summary="获取权限列表")
async def get_permissions_list(
		request: PermissionListRequest,
		db: DbDep,
		_: UserInDB = Depends(require_perm_manage),
) -> ApiResponse[PermissionListResponse]:
	"""
	获取权限列表（支持分页和模糊查询）
	- 可按权限名称、编码模糊查询
	- 可按权限类型筛选
	- 支持分页
	"""
	total, permissions = await permission_crud.get_permission_list(db, request)
	return ApiResponse.success(PermissionListResponse(
		total=total,
		items=[PermissionResponse.model_validate(p) for p in permissions]
	))


@router.get("/permissions/tree", response_model=ApiResponse[List[PermissionTreeResponse]], summary="获取权限树")
async def get_permissions_tree(
		db: DbDep,
		_: UserInDB = Depends(require_perm_manage),
) -> ApiResponse[List[PermissionTreeResponse]]:
	tree = await permission_crud.get_permissions_tree(db)
	return ApiResponse.success([PermissionTreeResponse.model_validate(node) for node in tree])


@router.post("/permissions", response_model=ApiResponse[PermissionResponse], summary="创建权限")
async def create_permission(
		request: PermissionCreate,
		db: DbDep,
		current_user: UserInDB = Depends(require_perm_manage),
		_audit: None = Depends(audit_log()),
		http_request: Request = None,
) -> ApiResponse[PermissionResponse]:
	permission_id = await permission_crud.create_permission(db, request)
	permission = await permission_crud.get_permission_by_id(db, permission_id)
	await audit_log_crud.create_audit_log(
		db=db, user_code=current_user.user_code, action="CREATE_PERMISSION",
		target_type="PERMISSION", target_id=str(permission_id),
		request_ip=http_request.client.host if http_request else "unknown",
		request_uri=str(http_request.url) if http_request else "/system/permissions",
	)
	return ApiResponse.success(PermissionResponse.model_validate(permission))


@router.put("/permissions/{permission_id}", response_model=ApiResponse[PermissionResponse], summary="更新权限")
async def update_permission(
		db: DbDep,
		_audit: AuditLogDep,
		permission_id: int, request: PermissionUpdate,
		current_user: UserInDB = Depends(require_perm_manage),
		http_request: Request = None,
) -> ApiResponse[PermissionResponse]:
	ok = await permission_crud.update_permission(db, permission_id, request)
	if not ok:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="权限不存在")
	permission = await permission_crud.get_permission_by_id(db, permission_id)
	await audit_log_crud.create_audit_log(
		db=db, user_code=current_user.user_code, action="UPDATE_PERMISSION",
		target_type="PERMISSION", target_id=str(permission_id),
		request_ip=http_request.client.host if http_request else "unknown",
		request_uri=str(http_request.url) if http_request else f"/system/permissions/{permission_id}",
	)
	return ApiResponse.success(PermissionResponse.model_validate(permission))


@router.delete("/permissions/{permission_id}", response_model=ApiResponse[dict], summary="删除权限")
async def delete_permission(
		db: DbDep,
		_audit: AuditLogDep,
		permission_id: int,
		current_user: UserInDB = Depends(require_perm_manage),
		http_request: Request = None,
) -> ApiResponse[dict]:
	ok = await permission_crud.delete_permission(db, permission_id)
	if not ok:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="权限不存在")
	await audit_log_crud.create_audit_log(
		db=db, user_code=current_user.user_code, action="DELETE_PERMISSION",
		target_type="PERMISSION", target_id=str(permission_id),
		request_ip=http_request.client.host if http_request else "unknown",
		request_uri=str(http_request.url) if http_request else f"/system/permissions/{permission_id}",
	)
	return ApiResponse.success(message="权限删除成功")


# ============ 审计日志 ============
@router.post("/audit-logs/list", summary="查询操作日志")
async def get_audit_logs(
		request: AuditLogRequest,
		db: DbDep,
		_: UserInDB = Depends(require_audit_view),
) -> ApiResponse[AuditLogListResponse]:
	total, logs = await audit_log_crud.get_audit_log_list(db, request)
	return ApiResponse.success(AuditLogListResponse(total=total, items=logs))


@router.get(
	"/audit-logs/stats",
	summary="获取操作统计",
	response_model=ApiResponse[OperationStatisticsResponse],  # ← 显式模型
)
async def get_operation_statistics(
		db: DbDep,
		start_time: str = Query(..., description="起始时间（ISO 格式，例：2025-01-01T00:00:00）"),
		end_time: str = Query(..., description="截止时间（ISO 格式，例：2025-09-06T23:59:59）"),
		_: UserInDB = Depends(require_audit_view),
) -> ApiResponse[OperationStatisticsResponse]:
	"""
	获取操作统计
	1. 解析 ISO 8601 时间串
	2. 校验时间范围
	3. 调用审计日志 CRUD 返回统计
	"""
	try:
		# 清理参数
		start_time = start_time.strip('"\'')
		end_time = end_time.strip('"\'')

		# 解析日期
		try:
			start_dt = datetime.fromisoformat(
				start_time.replace('Z', '+00:00') if 'Z' in start_time else start_time
			)
			end_dt = datetime.fromisoformat(
				end_time.replace('Z', '+00:00') if 'Z' in end_time else end_time
			)
		except ValueError as e:
			raise BizException.from_error_code(
				ErrorCode.BAD_REQUEST,
				message=f"日期格式错误: {str(e)}，请使用 ISO 8601 格式，如：2025-01-01T00:00:00"
			)

		# 校验时间范围
		if start_dt > end_dt:
			raise BizException.from_error_code(
				ErrorCode.BAD_REQUEST,
				message="起始时间不能晚于截止时间"
			)

		# 查询统计
		stats = await audit_log_crud.get_operation_statistics(db, start_dt, end_dt)
		return ApiResponse.success(OperationStatisticsResponse(**stats))

	except BizException:
		raise
	except Exception:
		raise BizException.from_error_code(
			ErrorCode.INTERNAL_SERVER_ERROR,
			message="获取操作统计失败"
		)


@router.get("/audit-logs/{log_id}", summary="获取日志详情")
async def get_audit_log_detail(
		log_id: int,
		db: DbDep,
		_: UserInDB = Depends(require_audit_view),
) -> ApiResponse[dict]:
	log = await audit_log_crud.get_audit_log_by_id(db, log_id)
	if not log:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="日志记录不存在")
	return ApiResponse.success(log.model_dump())


# ============ 设备负责人管理 ============

@router.put("/device/stations/{id}/manager", response_model=ApiResponse[dict], summary="设置台区负责人")
async def set_station_manager(
		db: DbDep,
		_audit: AuditLogDep,
		id: int,
		request: ManagerUpdateRequest,
		_: UserInDB = Depends(require_device_manage),

) -> ApiResponse[dict]:
	"""
	设置台区负责人
	"""
	success = await update_station_manager(db, id, request.manager_code)
	if not success:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="台区不存在")

	return ApiResponse.success(message="台区负责人设置成功")


@router.put("/device/boxes/{id}/manager", response_model=ApiResponse[dict], summary="设置电箱负责人")
async def set_box_manager(
		db: DbDep,
		_audit: AuditLogDep,
		id: int,
		request: ManagerUpdateRequest,
		_: UserInDB = Depends(require_device_manage),
) -> ApiResponse[dict]:
	"""
	设置电箱负责人
	"""
	success = await update_box_manager(db, id, request.manager_code)
	if not success:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="电箱不存在")

	return ApiResponse.success(message="电箱负责人设置成功")


@router.put("/device/rtus/{id}/manager", response_model=ApiResponse[dict], summary="设置RTU负责人")
async def set_rtu_manager(
		db: DbDep,
		_audit: AuditLogDep,
		id: int,
		request: ManagerUpdateRequest,
		_: UserInDB = Depends(require_device_manage),

) -> ApiResponse[dict]:
	"""
	设置RTU负责人
	"""
	success = await update_rtu_manager(db, id, request.manager_code)
	if not success:
		raise BizException.from_error_code(ErrorCode.NOT_FOUND, message="RTU不存在")

	return ApiResponse.success(message="RTU负责人设置成功")


# ============ 基础地址管理 ============

@router.get("/addresses", response_model=ApiResponse[AddressListResponse], summary="获取基础地址列表")
async def list_base_addresses(
		db: DbDep,
		_audit: AuditLogDep,
		page: PaginationDep,
		query: AddressListRequest = Depends(),
		_: UserInDB = Depends(require_address_view)
) -> ApiResponse[AddressListResponse]:
	"""获取基础地址列表"""
	try:
		total, items = await get_base_address_list(db, query, page.page, page.size)

		address_responses = [AddressResponse.model_validate(item) for item in items]
		result = AddressListResponse(
			total=total,
			items=address_responses
		)

		return ApiResponse.success(result, "基础地址列表获取成功")
	except Exception as e:
		return ApiResponse.error(f"获取基础地址列表失败: {str(e)}", code=500)


@router.get("/addresses/{id}", response_model=ApiResponse[AddressResponse], summary="获取基础地址详情")
async def get_base_address_detail(
		db: DbDep,
		id: int = Path(..., description="基础地址ID"),
		_: UserInDB = Depends(require_address_view)
) -> ApiResponse[AddressResponse]:
	"""获取基础地址详情"""
	try:
		address = await get_base_address_by_id(db, id)
		if not address:
			return ApiResponse.error("基础地址不存在", code=404)

		return ApiResponse.success(AddressResponse.model_validate(address), "基础地址详情获取成功")
	except Exception as e:
		return ApiResponse.error(f"获取基础地址详情失败: {str(e)}", code=500)


@router.post("/addresses", response_model=ApiResponse[AddressResponse], summary="创建基础地址")
async def create_base_address_endpoint(
		db: DbDep,
		_audit: AuditLogDep,
		payload: AddressCreate,
		_: UserInDB = Depends(require_address_manage)
) -> ApiResponse[AddressResponse]:
	"""创建基础地址"""
	try:
		address_id = await create_base_address(db, payload)
		address = await get_base_address_by_id(db, address_id)

		return ApiResponse.success(AddressResponse.model_validate(address), "基础地址创建成功")
	except Exception as e:
		return ApiResponse.error(f"创建基础地址失败: {str(e)}", code=500)


@router.put("/addresses/{id}", response_model=ApiResponse[AddressResponse], summary="更新基础地址")
async def update_base_address_endpoint(
		db: DbDep,
		_audit: AuditLogDep,
		id: int = Path(..., description="基础地址ID"),
		payload: AddressUpdate = Body(...),
		_: UserInDB = Depends(require_address_manage)
) -> ApiResponse[AddressResponse]:
	"""更新基础地址"""
	try:
		success = await update_base_address(db, id, payload)
		if not success:
			return ApiResponse.error("基础地址不存在", code=404)

		address = await get_base_address_by_id(db, id)
		return ApiResponse.success(AddressResponse.model_validate(address), "基础地址更新成功")
	except Exception as e:
		return ApiResponse.error(f"更新基础地址失败: {str(e)}", code=500)


@router.delete("/addresses/{id}", response_model=ApiResponse[dict], summary="删除基础地址")
async def delete_base_address_endpoint(
		db: DbDep,
		_audit: AuditLogDep,
		id: int = Path(..., description="基础地址ID"),
		_: UserInDB = Depends(require_address_manage)
) -> ApiResponse[dict]:
	"""删除基础地址"""
	try:
		success = await delete_base_address(db, id)
		if not success:
			return ApiResponse.error("基础地址不存在", code=404)

		return ApiResponse.success({}, "基础地址删除成功")
	except Exception as e:
		return ApiResponse.error(f"删除基础地址失败: {str(e)}", code=500)
